/*******************************************************************************
 * @(#)Utils.java 2015年6月19日
 * <p>
 * Copyright 2015 emrubik Group Ltd. All rights reserved.
 * EMRubik PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *******************************************************************************/
package com.inossem.utils.base;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.inossem.utils.constant.UtilsConstant;
import com.inossem.utils.log.LogUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Random;

import id.zelory.compressor.Compressor;


public class Utils {

    private static Toast toast;

    public static String getAppName(Context context, String packageName) {
        String result = "";
        try {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
            result = packageInfo.applicationInfo.loadLabel(context.getPackageManager()).toString();
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }


    public static void middleToast(Context context, String message) {
        if (toast == null) {
            toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        } else {
            toast.setText(message);
        }
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }

    public static String exceptionToString(Throwable throwable) {
        if (throwable == null) {
            return "";
        }
        String exceptionMessage = "";
        try {
            StringWriter sw = new StringWriter();
            throwable.printStackTrace(new PrintWriter(sw, true));
            exceptionMessage = sw.toString();
            sw.flush();
            sw.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return exceptionMessage;
    }

    public static boolean checkServiceByClassName(Context context, String className) {
        ActivityManager activityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> serviceList = activityManager
                .getRunningServices(Integer.MAX_VALUE);
        if (!serviceList.isEmpty()) {
            for (int i = 0; i < serviceList.size(); i++) {
                if (serviceList.get(i).service.getClassName().equals(className)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static long getTimeStampFromString(String format, String time) {
        return getDateFromString(format, time).getTime();
    }

    public static Date getDateFromString(String format, String time) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.getDefault());
        Date date = null;
        try {
            date = dateFormat.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static String getStringDateFromTimeStamp(String format, long date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.getDefault());
        return dateFormat.format(new Date(date));
    }

    public static String getStringDateFromDate(String format, Date date) {
        String result;
        result = new SimpleDateFormat(format, Locale.getDefault()).format(date);
        return result;
    }

    public static String getCurrentStringDate(String format) {
        Calendar calendar = Calendar.getInstance();
        return getStringDateFromDate(format, calendar.getTime());
    }

    public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
        Bitmap roundCornerBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
                Config.ARGB_8888);
        Canvas canvas = new Canvas(roundCornerBitmap);
        int color = 0xff424242;// int color = 0xff424242;
        Paint paint = new Paint();
        paint.setColor(color);
        // 防止锯齿
        paint.setAntiAlias(true);
        Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        RectF rectF = new RectF(rect);
        float roundPx = pixels;
        // 相当于清屏
        canvas.drawARGB(0, 0, 0, 0);
        // 先画了一个带圆角的矩形
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        // 再把原来的bitmap画到现在的bitmap！！！注意这个理解
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return roundCornerBitmap;
    }

    public static int dpToPx(Context context, int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context
                .getResources().getDisplayMetrics());
    }

    public static double mul(double multiplier, double faciend) {
        double result = faciend * multiplier;
        return result;
    }

    public static double division(double dividend, double divisor) {
        double result = 0;
        if (divisor != 0) {
            result = dividend / divisor;
        } else {
            result = 0;
        }
        return result;
    }

    public static void catchException(Context context, Throwable throwable) {
        StringWriter sw = new StringWriter();
        throwable.printStackTrace(new PrintWriter(sw, true));
        String exceptionMessage = sw.toString();
        if (context != null) {
            LogUtils.logThrowableE(context, exceptionMessage, throwable);
        }
    }

    public static Bitmap toGray(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Bitmap faceIconGreyBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        Canvas canvas = new Canvas(faceIconGreyBitmap);
        Paint paint = new Paint();
        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.setSaturation(0);
        ColorMatrixColorFilter colorMatrixFilter = new ColorMatrixColorFilter(colorMatrix);
        paint.setColorFilter(colorMatrixFilter);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        return faceIconGreyBitmap;
    }

    public static Bitmap drawableToBitmap(Drawable drawable) {
        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
                        : Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);
        return bitmap;

    }

    public static Drawable bitmapToDrawble(Context context, Bitmap bitmap) {
        Drawable drawable = new BitmapDrawable(context.getResources(), bitmap);
        return drawable;
    }

    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public static boolean delFileOrFolder(String path) {
        return delFileOrFolder(new File(path));
    }

    public static boolean delFileOrFolder(File file) {
        if (file != null && file.exists()) {
            if (file.isFile()) {
                file.delete();
            } else if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null) {
                    File[] var2 = files;
                    int var3 = files.length;
                    for (int var4 = 0; var4 < var3; ++var4) {
                        File sonFile = var2[var4];
                        delFileOrFolder(sonFile);
                    }
                }
                file.delete();
            }
        }
        return true;
    }

    @SuppressLint("NewApi")
    public static int getBitmapSize(Bitmap bitmap) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // API 19
            return bitmap.getAllocationByteCount();
        }
        return bitmap.getRowBytes() * bitmap.getHeight(); // earlier version
    }

    public static File bitmapToFile(String filePath, Bitmap bitmap) {
        File file = new File(filePath);// 将要保存图片的路径
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    public static String getVersionName(Context context) {
        String result = "";
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0);
            result = info.versionName;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static Integer getVersionCode(Context context) {
        Integer result = null;
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo info = packageManager.getPackageInfo(context.getPackageName(), 0);
            result = info.versionCode;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }


    public static boolean deleteFolder(String path) {
        boolean result = true;
        File file = new File(path);
        if (!file.exists()) {
            return false;
        }
        if (!file.isDirectory()) {
            return false;
        } else {
            File[] fileItemList = file.listFiles();
            for (int i = 0; i < fileItemList.length; i++) {
                File fileItem = fileItemList[i];
                if (fileItem.isFile()) {
                    boolean fileFlag = deleteFile(fileItem.getAbsolutePath());
                    if (!fileFlag) {
                        result = false;
                    }
                } else if (fileItem.isDirectory()) {
                    boolean folderFlag = deleteFolder(fileItem.getAbsolutePath());
                    if (!folderFlag) {
                        result = false;
                    }
                }
            }
            boolean currentFolderFlag = file.delete();
            if (!currentFolderFlag) {
                result = false;
            }
            return result;

        }
    }

    public static boolean deleteFile(String path) {
        boolean result = false;
        File file = new File(path);
        if (!file.exists()) {
            return result;
        }
        if (!file.isFile()) {
            return result;
        } else {
            return file.delete();
        }
    }

    public static void closeSoftKeyboard(Context context, View view) {
        InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            return;
        }
        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();

        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }


    /**
     * 去重复元素,把ls1中的元素插入到ls2之前
     *
     * @param ls1
     * @param ls2
     * @param <T>
     * @return
     */
    public static <T> List<T> addNoDuplicate(List<T> ls1, List<T> ls2) {
        for (int i = ls1.size() - 1; i >= 0; i--) {
            T l = ls1.get(i);
            if (!ls2.contains(ls1.get(i))) {
                ls2.add(0, l);
            }
        }
        return ls2;
    }

    /**
     * 得到SD卡根目录.
     */
    public static File getRootPath(Context context) {
        if (sdCardIsAvailable()) {
            return Environment.getExternalStorageDirectory(); // 取得sdcard文件路径
        } else {
            return context.getFilesDir();
        }
    }

    /**
     * SD卡是否可用.
     */
    public static boolean sdCardIsAvailable() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File sd = new File(Environment.getExternalStorageDirectory().getPath());
            return sd.canWrite();
        } else
            return false;
    }

    //将字节转成B或KB或MB或GB，保留2位小时
    public static String getPrintSize(long size) {
        //如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        if (size < 1024) {
            return String.valueOf(size) + "B";
        } else {
            size = size / 1024;
        }
        //如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        //因为还没有到达要使用另一个单位的时候
        //接下去以此类推
        if (size < 1024) {
            return String.valueOf(size) + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            //因为如果以MB为单位的话，要保留最后1位小数，
            //因此，把此数乘以100之后再取余
            size = size * 100;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "MB";
        } else {
            //否则如果要以GB为单位的，先除于1024再作同样的处理
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "GB";
        }
    }

    public static long getBeginOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime().getTime();
    }

    public static long getEndOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        return calendar.getTime().getTime();
    }

    //通过旋转角度获取未旋转的图片
    public static Bitmap getNotRotateBitmap(Bitmap bitmap, int degree) {
        if (degree == UtilsConstant.ROTATE_DEGREE_0) {
            return bitmap;
        } else {
            Matrix matrix = new Matrix();
            matrix.postRotate(degree);
            return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }
    }

    //获取旋转角度
    public static int getImageDegree(String imagePath) {
        int result = UtilsConstant.ROTATE_DEGREE_0;
        ExifInterface exifInterface;
        try {
            exifInterface = new ExifInterface(imagePath);
            // 读取图片中相机方向信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);
            // 计算旋转角度
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    result = UtilsConstant.ROTATE_DEGREE_90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    result = UtilsConstant.ROTATE_DEGREE_180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    result = UtilsConstant.ROTATE_DEGREE_270;
                    break;
                default:
                    result = UtilsConstant.ROTATE_DEGREE_0;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    //通过uri获取图片全路径
    public static String getImageFilePathFromUri(Context context, Uri uri) {
        String[] filePathColumns = {MediaStore.Images.Media.DATA};
        Cursor imageCursor = context.getContentResolver().query(uri, filePathColumns, null, null, null);
        imageCursor.moveToFirst();
        int columnIndex = imageCursor.getColumnIndex(filePathColumns[0]);
        String imagePath = imageCursor.getString(columnIndex);
        imageCursor.close();
        return imagePath;
    }

    //图片文件压缩成File
    public static File compressImageToFile(Context context, File imageFile, int maxWidth, int maxHeight, Bitmap.CompressFormat compressFormat, int quality, String destinationDirectoryPath) throws IOException {
        return new Compressor(context)
                .setMaxWidth(maxWidth)
                .setMaxHeight(maxHeight)
                .setCompressFormat(compressFormat)
                .setQuality(quality)
                .setDestinationDirectoryPath(destinationDirectoryPath)
                .compressToFile(imageFile);
    }

    //图片文件压缩成Bitmap
    public static Bitmap compressImageToBitmap(Context context, File imageFile, int maxWidth, int maxHeight, Bitmap.CompressFormat compressFormat, int quality, String destinationDirectoryPath) throws IOException {
        return new Compressor(context)
                .setMaxWidth(maxWidth)
                .setMaxHeight(maxHeight)
                .setCompressFormat(compressFormat)
                .setQuality(quality)
                .setDestinationDirectoryPath(destinationDirectoryPath)
                .compressToBitmap(imageFile);
    }
}
